﻿using System;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.IO;


namespace ConsoleSocketsDemo
{
    class SocketServer
    {
        Socket sRecvCmd;

        int recvCmdPort;//接收图片请求命令
        int sendPicPort;//发送图片命令

        public SocketServer(int recvPort,int sendPort)
        {
            recvCmdPort = recvPort;
            sendPicPort = sendPort;

            //建立本地socket，一直对4000端口进行侦听            
            IPEndPoint recvCmdLocalEndPoint = new IPEndPoint(IPAddress.Any, recvCmdPort);
            sRecvCmd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sRecvCmd.Bind(recvCmdLocalEndPoint);
            sRecvCmd.Listen(100);
        }       
        
        public void thread()
        {
            while (true)
            {
                System.Threading.Thread.Sleep(1);//每个线程内部的死循环里面都要加个“短时间”睡眠，使得线程占用资源得到及时释放
                
                try
                {

                    Socket sRecvCmdTemp = sRecvCmd.Accept();//Accept 以同步方式从侦听套接字的连接请求队列中提取第一个挂起的连接请求，然后创建并返回新的 Socket
                    
                    sRecvCmdTemp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);//设置接收数据超时                    
                    sRecvCmdTemp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);//设置发送数据超时                   
                    sRecvCmdTemp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, 1024); //设置发送缓冲区大小 1K                   
                    sRecvCmdTemp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, 1024);//设置接收缓冲区大小1K


                    byte[] recvBytes = new byte[1024];//开启一个缓冲区，存储接收到的信息
                    sRecvCmdTemp.Receive(recvBytes); //将读得的内容放在recvBytes中                   
                    string strRecvCmd = Encoding.Default.GetString(recvBytes);//
                    //程序运行到这个地方，已经能接收到远程发过来的命令了
                    
                    //*************
                    //解码命令，并执行相应的操作----如下面的发送本机图片
                    //*************
                    string[] strArray = strRecvCmd.Split(';');
                    if (strArray[0] == "PicRequest")
                    {
                        string[] strRemoteEndPoint = sRecvCmdTemp.RemoteEndPoint.ToString().Split(':');//远处终端的请求端IP和端口，如：127.0.0.1：4000
                        string strRemoteIP = strRemoteEndPoint[0];
                        SentPictures(strRemoteIP, sendPicPort); //发送本机图片文件                  

                        recvBytes = null;
                    }
                    
                }
                catch(Exception ex)
                {
                    Console.Write(ex.Message);                    
                }
            }
           
        }

        /// <summary>
        /// 向远程客户端发送图片
        /// </summary>
        /// <param name="strRemoteIP">远程客户端IP</param>
        /// <param name="sendPort">发送图片的端口</param>
        private static void SentPictures(string strRemoteIP, int sendPort)
        {

            string path = @"C:\Users\Admin\Desktop\数据校验";
            string strImageTag = "image";//图片名称中包含有image的所有图片文件
            
            try
            {
                string[] picFiles = Directory.GetFiles(path, strImageTag + "*", SearchOption.TopDirectoryOnly);//满足要求的文件个数

                if (picFiles.Length == 0)
                {
                    return;//没有图片，不做处理                   
                }

                long sendBytesTotalCounts = 0;//发送数据流总长度

                //消息头部：命令标识+文件数目+……文件i长度+
                string strMsgHead = "PicResponse;" + picFiles.Length + ";";
                
                

                //消息体：图片文件流
                byte[][] msgPicBytes = new byte[picFiles.Length][];
                for (int j = 0; j < picFiles.Length; j++)
                {
                    FileStream fs = new FileStream(picFiles[j].ToString(), FileMode.Open, FileAccess.Read);
                    BinaryReader reader = new BinaryReader(fs);
                    msgPicBytes[j] = new byte[fs.Length];
                    strMsgHead += fs.Length.ToString() + ";";
                    sendBytesTotalCounts += fs.Length;
                    reader.Read(msgPicBytes[j], 0, msgPicBytes[j].Length);                  
                }

                byte[] msgHeadBytes = Encoding.Default.GetBytes(strMsgHead);//将消息头字符串转成byte数组
                sendBytesTotalCounts += msgHeadBytes.Length;
                //要发送的数据流:数据头＋数据体
                byte[] sendMsgBytes = new byte[sendBytesTotalCounts];//要发送的总数组

                for (int i = 0; i < msgHeadBytes.Length; i++)
                {
                    sendMsgBytes[i] = msgHeadBytes[i]; //数据头
                }


                int index = msgHeadBytes.Length;
                for (int i = 0; i < picFiles.Length; i++)
                {

                    for (int j = 0; j < msgPicBytes[i].Length; j++)
                    {
                        sendMsgBytes[index + j] = msgPicBytes[i][j];
                    }
                    index += msgPicBytes[i].Length;
                }
                //程序执行到此处，带有图片信息的报文已经准备好了
                //PicResponse;2;94223;69228;
                //+图片1比特流+……图片2比特流                

                try
                {
                    #region 发送图片
                    Socket sSendPic = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                    
                    IPAddress ipAddress = IPAddress.Parse(strRemoteIP);//remoteip = "127.0.0.1"  


                    try
                    {
                        sSendPic.Connect(ipAddress, sendPort);//连接无端客户端主机                     
                        sSendPic.Send(sendMsgBytes, sendMsgBytes.Length, 0);//发送本地图片
                    }
                    catch (System.Exception e)
                    {                        
                        System.Console.Write("SentPictures函数在建立远程连接时出现异常：" + e.Message);
                    }finally
                    {  
                        sSendPic.Close();
                    }
                    #endregion
                }
                catch
                {
                }
                
                
            }
            catch(Exception ex)
            {
                Console.Write(ex.Message);
            }
              
        }


    }
}
